package storage

import (
	"context"

	"gitcode.com/eteam/sae.git/types"
	"go.mongodb.org/mongo-driver/v2/bson"
	"go.mongodb.org/mongo-driver/v2/mongo"
	"go.mongodb.org/mongo-driver/v2/mongo/options"
)

type FormFieldDbItem struct {
	Name        string              `bson:"name"`
	Description string              `bson:"description"`
	Key         string              `bson:"key"`
	Value       string              `bson:"value"`
	ValueType   types.FormFieldType `bson:"valueType"`
	Optional    bool                `bson:"optional"`
}

type FormDefineInfoDbItem struct {
	FormDefineId string            `bson:"_id"`
	TaskId       string            `bson:"taskId"`
	FormType     string            `bson:"formType"`
	Name         string            `bson:"name"`
	Description  string            `bson:"description"`
	TimeStamp    int64             `bson:"timeStamp"`
	Fields       []FormFieldDbItem `bson:"fields"`
}

func (item *FormDefineInfoDbItem) SaveFileValue(key, value string) {
	for index, field := range item.Fields {
		if field.Key == key {
			item.Fields[index].Value = value
		}
	}
}

func (item *FormDefineInfoDbItem) ToFormDefine() *types.FormDefine {
	if item == nil {
		return nil
	}
	fields := []types.FormField{}
	for _, field := range item.Fields {
		fields = append(fields, types.FormField{
			Name:        field.Name,
			Description: field.Description,
			Key:         field.Key,
			Value:       field.Value,
			ValueType:   field.ValueType,
			Optional:    field.Optional,
		})
	}
	return &types.FormDefine{
		FormDefineId: item.FormDefineId,
		FormType:     item.FormType,
		Name:         item.Name,
		Description:  item.Description,
		TimeStamp:    item.TimeStamp,
		Fields:       fields,
	}
}

type _FormDefineInfoDao struct {
	mc *mongo.Collection
}

func newFormDefineInfoDao(db *mongo.Database) (*_FormDefineInfoDao, error) {
	mc := db.Collection("form_define_info")
	_, err := mc.Indexes().CreateOne(context.Background(), mongo.IndexModel{
		Keys: bson.D{{"taskId", 1}, {"timeStamp", 1}},
	})
	if err != nil {
		return nil, err
	}
	return &_FormDefineInfoDao{mc: mc}, nil
}

func (dao *_FormDefineInfoDao) Insert(ctx context.Context, dbItem *FormDefineInfoDbItem) error {
	_, err := dao.mc.InsertOne(ctx, dbItem)
	return err
}

func (dao *_FormDefineInfoDao) ListByTask(ctx context.Context, taskIdList []string) ([]*FormDefineInfoDbItem, error) {
	if len(taskIdList) == 0 {
		return []*FormDefineInfoDbItem{}, nil
	}
	cursor, err := dao.mc.Find(ctx, bson.M{"taskId": bson.M{"$in": taskIdList}},
		options.Find().SetSort(bson.M{"timeStamp": 1}))
	if err != nil {
		return nil, err
	}
	retList := []*FormDefineInfoDbItem{}
	err = cursor.All(ctx, &retList)
	return retList, err
}

func (dao *_FormDefineInfoDao) Update(ctx context.Context, dbItem *FormDefineInfoDbItem) error {
	_, err := dao.mc.UpdateOne(ctx, bson.M{"_id": dbItem.FormDefineId}, bson.M{"$set": dbItem})
	return err
}
